﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using NosoiFigthersWeb.db;
using NosoiFigthersWeb.datacontracts;
using ComplexNetGeneratorLib;
using System.Xml;

namespace NosoiFigthersWeb
{
    /// <summary>
    /// Summary description for DataProviderService
    /// </summary>
    [WebService(Namespace = "DataProviderService")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class DataProviderService : System.Web.Services.WebService
    {
        #region methods for Disease

        [WebMethod]
        public string[] GetAvailableDiseases()
        {
			
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
            if (db.DatabaseExists() == false)
				return new string[0];
            
            var diseases = from d in db.Diseases select d;
			
            List<string> strList = new List<string>();
            foreach (var d in diseases)
            {
                strList.Add(d.name);
            }

            return strList.ToArray();
        }

        [WebMethod]
        public string[] GetDisease(string name)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new string[0];
            
            var disease = (from d in db.Diseases where d.name == name select d).Single();
            string[] toReturn = new string[2];
            toReturn[0] = disease.data.Value; //xml
            toReturn[1] = disease.description; // description
            return toReturn;
        }

        [WebMethod]
        public void SetDisease(string name, string data, string desc)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return;
            
            Disease disease = new Disease();
            disease.name = name;
            XmlDocument xmlDoc = new XmlDocument();
            var doc  = new System.Xml.Linq.XDocument();
            var wrt = doc.CreateWriter();
            wrt.WriteString(data);
            wrt.Close();
            disease.data = doc.Root;
            disease.description = desc;
            db.Diseases.InsertOnSubmit(disease);
            db.SubmitChanges();
        }

        [WebMethod]
        public void UpdateDisease(string name, string data, string desc)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return;
            
            var disease = (from d in db.Diseases where d.name == name select d).Single();
            disease.name = name;
            XmlDocument xmlDoc = new XmlDocument();
            var doc = new System.Xml.Linq.XDocument();
            var wrt = doc.CreateWriter();
            wrt.WriteString(data);
            wrt.Close();
            disease.data = doc.Root;
            disease.description = desc;
            db.SubmitChanges();
        }
        
        [WebMethod]
        public void RemoveDisease(string name)
        {
			DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return;
			
			var disease = (from d in db.Diseases where d.name == name select d).Single();
			db.Diseases.DeleteOnSubmit(disease);
			db.SubmitChanges();
        }

        #endregion

        #region methods for FormTemplate

        [WebMethod]
        public string[] GetAvailableFormTemplates()
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new string[0];
            
            var templates = from t in db.FormTemplates select t;

            List<string> strList = new List<string>();
            foreach (var t in templates)
            {
                strList.Add(t.name);
            }

            return strList.ToArray();
        }

        [WebMethod]
        public string[] GetFormTemplateByName(string name)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new string[0];
            
            var template = (from t in db.FormTemplates where t.name == name select t).Single();
            string[] toReturn = new string[2];
            toReturn[0] = template.id.ToString(); //id
            toReturn[1] = template.data; //xml
            return toReturn;
        }

        [WebMethod]
        public string[] GetFormTemplateById(int id)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new string[0];
            
            var template = (from t in db.FormTemplates where t.id == id select t).Single();
            string[] toReturn = new string[2];
            toReturn[0] = template.name; //name
            toReturn[1] = template.data; //xml
            return toReturn;
        }

        [WebMethod]
        public void SetFormTemplate(string name, string data)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return;
            
            FormTemplate temp = new FormTemplate();
            temp.name = name;
            temp.data = data;
            db.FormTemplates.InsertOnSubmit(temp);
            db.SubmitChanges();
        }

        [WebMethod]
        public void UpdateFormTemplate(int id, string name, string data)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return;
            
            var template = (from t in db.FormTemplates where t.id == id select t).Single();
            template.name = name;
            template.data = data;
            db.SubmitChanges();
        }

        #endregion

        #region methods for Form

        [WebMethod]
        public string[] GetAvailableForms()
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new string[0];
            
            var forms = from f in db.Forms select f;

            List<string> strList = new List<string>();
            foreach (var f in forms)
            {
                strList.Add(f.name);
            }

            return strList.ToArray();
        }

        [WebMethod]
        public string[] GetFormByName(string name)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new string[0];
            
            var form = (from f in db.Forms where f.name == name select f).Single();
            string[] toReturn = new string[3];
            toReturn[0] = form.id.ToString(); //id
            toReturn[1] = form.data; //xml
            toReturn[2] = form.template.ToString(); //templateID
            return toReturn;
        }

        [WebMethod]
        public string[] GetFormById(int id)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new string[0];
            
            var form = (from f in db.Forms where f.id == id select f).Single();
            string[] toReturn = new string[3];
            toReturn[0] = form.name; //name
            toReturn[1] = form.data; //xml
            toReturn[2] = form.template.ToString(); //templateID
            return toReturn;
        }

        [WebMethod]
        public void SetForm(string name, string data, int template)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return;
            
            Form form = new Form();
            form.name = name;
            form.data = data;
            form.template = template;
            db.Forms.InsertOnSubmit(form);
            db.SubmitChanges();
        }

        [WebMethod]
        public void UpdateForm(int id, string name, string data, int template)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return;
            
            var form = (from f in db.Forms where f.id == id select f).Single();
            form.name = name;
            form.data = data;
            form.template = template;
            db.SubmitChanges();
        }

        #endregion

        #region methods for Node

        [WebMethod]
        public NodeDC[] GetNodes()
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false) return null;
            var nodes = from n in db.Nodes select n;
            List<NodeDC> list = new List<NodeDC>();
            foreach (var n in nodes)
            {
                NodeDC node = new NodeDC();
                node.nodeID = n.nodeID;
                node.name = n.name;
                node.surname = n.surname;
                node.birthdate = n.birthdate;
                node.image = n.image;
                node.latitude = n.latitude;
                node.longitude = n.longitude;
                node.street = n.street;
                node.town = n.town;
                node.postalcode = n.postalcode;
                node.country = n.country;
                list.Add(node);
            }
            return list.ToArray();
        }

        [WebMethod]
        public NodeDC GetNodeById(int id)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false) return null;
            var node = (from n in db.Nodes where n.nodeID == id select n).Single();
            NodeDC nodeDC = new NodeDC();
            nodeDC.nodeID = node.nodeID;
            nodeDC.name = node.name;
            nodeDC.surname = node.surname;
            nodeDC.birthdate = node.birthdate;
            nodeDC.image = node.image;
            nodeDC.latitude = node.latitude;
            nodeDC.longitude = node.longitude;
            nodeDC.street = node.street;
            nodeDC.town = node.town;
            nodeDC.postalcode = node.postalcode;
            nodeDC.country = node.country;
            return nodeDC;
        }

        [WebMethod]
        public NodeDC GetNodeByName(string name)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false) return null;
            var node = (from n in db.Nodes where n.name == name select n).Single();
            NodeDC nodeDC = new NodeDC();
            nodeDC.nodeID = node.nodeID;
            nodeDC.name = node.name;
            nodeDC.surname = node.surname;
            nodeDC.birthdate = node.birthdate;
            nodeDC.image = node.image;
            nodeDC.latitude = node.latitude;
            nodeDC.longitude = node.longitude;
            nodeDC.street = node.street;
            nodeDC.town = node.town;
            nodeDC.postalcode = node.postalcode;
            nodeDC.country = node.country;
            return nodeDC;
        }

        [WebMethod]
        public int NewNodeStr(string name, string surname, DateTime birthdate, int image,
            double latitude, double longitude, string street, string town, string postalcode, string country)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false) return -1;
            Node node = new Node();
            node.name = name;
            node.surname = surname;
            node.birthdate = birthdate;
            node.image = image;
            node.latitude = latitude;
            node.longitude = longitude;
            node.street = street;
            node.town = town;
            node.postalcode = postalcode;
            node.country = country;
            db.Nodes.InsertOnSubmit(node);
            db.SubmitChanges();
            return node.nodeID;
        }

        [WebMethod]
        public int NewNode(NodeDC nodeDC)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
            if (db.DatabaseExists() == false) return -1;
            Node node = new Node();
            node.name = nodeDC.name;
            node.surname = nodeDC.surname;
            node.birthdate = nodeDC.birthdate;
            node.image = nodeDC.image;
            node.latitude = nodeDC.latitude;
            node.longitude = nodeDC.longitude;
            node.street = nodeDC.street;
            node.town = nodeDC.town;
            node.postalcode = nodeDC.postalcode;
            node.country = nodeDC.country;
            db.Nodes.InsertOnSubmit(node);
            db.SubmitChanges();
            return node.nodeID;
        }

        [WebMethod]
        public void UpdateNode(int nodeID, string name, string surname, DateTime birthdate, int image,
            float latitude, float longitude, string street, string town, string postalcode)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return;
            
            var node = (from n in db.Nodes where n.nodeID == nodeID select n).Single();
            node.nodeID = nodeID;
            node.name = name;
            node.surname = surname;
            node.birthdate = birthdate;
            node.image = image;
            node.latitude = latitude;
            node.longitude = longitude;
            node.street = street;
            node.town = town;
            node.postalcode = postalcode;
            db.SubmitChanges();
        }

        #endregion

        #region methods for Edge

        [WebMethod]
        public string[] GetEdges()
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new string[0];
            
            var edge = from e in db.Edges select e;

            List<string> strList = new List<string>();
            foreach (var e in edge)
            {
                strList.Add("netID: " + e.netID + " edgeID " + e.edgeID + " " + e.leftNodeID + "<->" + e.rightNodeID);
            }

            return strList.ToArray();
        }

        [WebMethod]
        public int[] GetEdgesIDs()
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new int[0];
            
            var edge = from e in db.Edges select e;

            List<int> strList = new List<int>();
            foreach (var e in edge)
            {
                strList.Add(e.edgeID);
            }

            return strList.ToArray();
        }

        [WebMethod]
        public int[] GetEdgeById(int id)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return new int[0];
            
            var edge = (from e in db.Edges where e.edgeID == id select e).Single();
            int[] toReturn = new int[4];
            toReturn[0] = edge.edgeID;
            toReturn[1] = edge.leftNodeID;
            toReturn[2] = edge.rightNodeID;
            toReturn[3] = edge.netID;
            return toReturn;
        }

        [WebMethod]
        public void NewEdge(int leftNodeID, int rightNodeID, int netID)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false) return;            
            Edge edge = new Edge();
            edge.leftNodeID = leftNodeID;
            edge.rightNodeID = rightNodeID;
            edge.netID = netID;
            db.Edges.InsertOnSubmit(edge);
            db.SubmitChanges();
        }

        [WebMethod]
        public void NewEdges(EdgeDC[] edges)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
            if (db.DatabaseExists() == false) return;
            foreach (var e in edges)
            {
                Edge edge = new Edge();
                edge.leftNodeID = e.leftNodeID;
                edge.rightNodeID = e.rightNodeID;
                edge.netID = e.netID;
                db.Edges.InsertOnSubmit(edge);
            }
            db.SubmitChanges();
        }

        [WebMethod]
        public void UpdateEdge(int edgeID, int leftNodeID, int rightNodeID, int netID)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			if (db.DatabaseExists() == false)
				return;
            
            var edge = (from e in db.Edges where e.edgeID == edgeID select e).Single();
            edge.edgeID = edgeID;
            edge.leftNodeID = leftNodeID;
            edge.rightNodeID = rightNodeID;
            edge.netID = netID;
            db.SubmitChanges();
        }

        #endregion

        #region methods for Net

        [WebMethod]
        public string[] GetAvailableNets()
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
            if (db.DatabaseExists() == false) return new string[0];
            var nets = from n in db.Nets select n;
            List<string> strList = new List<string>();
            foreach (var n in nets)
            {
                strList.Add(n.netName);
            }
            return strList.ToArray();
        }

        [WebMethod]
        public string netToDataBase(string name, ComplexNet complexNet, double latMin, double latMax, double longMin, double longMax)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
            Net net = new Net();
            net.netName = name;
            db.Nets.InsertOnSubmit(net);
            db.SubmitChanges();

            Random random = new Random();
            foreach (var n in complexNet.nodes)
            {
                Node node = new Node();
                node.name = n.id;
                node.latitude = latMin+(latMax-latMin)*random.NextDouble();
                node.longitude = longMin + (longMax - longMin) * random.NextDouble();
                db.Nodes.InsertOnSubmit(node);
            }
            db.SubmitChanges();
            
            var nodes = from n in db.Nodes select n;

            foreach (var e in complexNet.edges)
            {
                Edge edge = new Edge();
                edge.netID = net.netID;
                edge.leftNodeID = ((from n in db.Nodes where n.name == e.source.id select n).Single()).nodeID;
                edge.rightNodeID = ((from n in db.Nodes where n.name == e.target.id select n).Single()).nodeID;
                db.Edges.InsertOnSubmit(edge);
            }
            db.SubmitChanges();
            return net.netName;
        }

        [WebMethod]
        public string generateScaleFreeNet(string netName, int netPopulation)
        {
            ComplexNetGenerator generator = new ComplexNetGenerator();
            ComplexNet complexNet = generator.generateScaleFree(netPopulation,1,1);
            return netToDataBase(netName, complexNet, 52.17, 52.27, 20.88, 21.17);
        }

        #endregion


        [WebMethod]
        public int uploadImage(byte[] imgData)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
            Image image = new Image();
            image.data = imgData;
            db.Images.InsertOnSubmit(image);
            db.SubmitChanges();
            return image.id;
        }
    }
}
